package com.weimob.mcloud.wechatwork.customer.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
import com.google.common.collect.Lists;
import com.weimob.mcloud.wechatwork.common.utils.JsonUtil;
import com.weimob.mcloud.wechatwork.core.adapter.enums.app.StypeEnum;
import com.weimob.mcloud.wechatwork.core.adapter.pojo.dto.channel.request.SendDkOrSelfAgentMessageDTO;
import com.weimob.mcloud.wechatwork.core.adapter.pojo.dto.channel.request.SendMessageReqDTO;
import com.weimob.mcloud.wechatwork.core.adapter.pojo.dto.channel.response.SendMessageRespDTO;
import com.weimob.mcloud.wechatwork.core.adapter.pojo.dto.ec.request.BatchMigrationStatusRequest;
import com.weimob.mcloud.wechatwork.core.adapter.pojo.dto.ec.response.BatchMigrationStatusVo;
import com.weimob.mcloud.wechatwork.core.adapter.service.ChannelAdapterService;
import com.weimob.mcloud.wechatwork.core.adapter.service.EcAdapterService;
import com.weimob.mcloud.wechatwork.core.base.MultiResponse;
import com.weimob.mcloud.wechatwork.core.entity.config.clue.ClueCfg;
import com.weimob.mcloud.wechatwork.core.entity.privatesphere.PrivateSphere;
import com.weimob.mcloud.wechatwork.core.entity.privatesphere.PrivateSphereVid;
import com.weimob.mcloud.wechatwork.core.entity.relation.employee.Employee;
import com.weimob.mcloud.wechatwork.core.entity.relation.sid.SidInfo;
import com.weimob.mcloud.wechatwork.core.enums.employee.EmployeeActiveStatusEnum;
import com.weimob.mcloud.wechatwork.core.enums.employee.EmployeeStatusEnum;
import com.weimob.mcloud.wechatwork.core.service.sid.SidInfoService;
import com.weimob.mcloud.wechatwork.core.service.sid.request.SingleSidInfoRequest;
import com.weimob.mcloud.wechatwork.customer.convertor.bos.PrivateSphereCovert;
import com.weimob.mcloud.wechatwork.customer.domain.CustomerRemindMsgDTO;
import com.weimob.mcloud.wechatwork.customer.domain.EmployeeDeleteCustomerMsgDTO;
import com.weimob.mcloud.wechatwork.customer.externalDependencyProxy.usermanagement.EmployeeProxy;
import com.weimob.mcloud.wechatwork.customer.service.MsgNoticeService;
import com.weimob.mcloud.wechatwork.customer.service.user.base.PrivateSphereDTO;
import com.weimob.mcloud.wechatwork.customer.service.user.exception.BizException;
import com.weimob.mcloud.wechatwork.customer.service.user.module.dto.msg.CustomerLoseNoticeDTO;
import com.weimob.mcloud.wechatwork.customer.third.BosThird;
import com.weimob.mcloud.wechatwork.customer.third.NewRemoteOutServiceProxy;
import com.weimob.mcloud.wechatwork.customer.third.PrivateSphereThird;
import com.weimob.soa.common.response.SoaResponse;
import com.weimob.soa.common.utils.SoaUtil;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author junlong.lv
 * @version 1.0
 * @date 2021/11/30 4:29 下午
 */
@Slf4j
@Service
public class MsgNoticeServiceImpl implements MsgNoticeService {


    @Autowired
    private PrivateSphereThird privateSphereThird;


    @Autowired
    private ChannelAdapterService channelAdapterService;

    @Value("${stop.customer.lose.consume.on:false}")
    private Boolean stopCustomerLoseConsumeOn;

    @Reference
    private EcAdapterService ecAdapterService;

    @Autowired
    private BosThird bosThird;

    @Autowired
    private NewRemoteOutServiceProxy newRemoteOutServiceProxy;

    @Autowired
    private SidInfoService sidInfoService;


    @ApolloJsonValue("${stage_jump_url.by.tcode}")
    private Map<String, String> stageJumpUrlMap;

    @Value("${jump.customer.params:?sid=%s&externalUserId=%s&sendScene=%s}")
    private String jumpCustomerParams;

    /**
     * 异常code
     */
    @ApolloJsonValue("${send.msg.soa.code:['100300600157']}")
    private List<String> codeList;

    public static final String externalUserDelUser = "客户[%s]把你从好友列表删除了,建议重新添加好友或共享给同事\t <a href=\"%s\">客户详情</a> ";

    public static final String customerDelEmployeeWarn = "员工删除客户报警:员工【%s】今日删除客户数达到%s人，请关注";

    public static final String customerFollowRemind = "【提醒跟进客户】阶段: %s \n 客户状态: 跟进内容未填写 \n 跟进说明: %s \n<a href=\"%s\">查看详情</a>";

    private final String BATCH_CUSTOMER = "batch_customer";

    @Resource
    EmployeeProxy employeeProxy;

    @Override
    public Boolean customerLoseNotice(CustomerLoseNoticeDTO customerLoseNoticeDTO) {
        log.info("外部联系人流失消息提醒, 消息推送, request:{}", JSON.toJSONString(customerLoseNoticeDTO));

        PrivateSphereDTO privateSphereDTO = customerLoseNoticeDTO.getPrivateSphereDTO();
        PrivateSphere privateSphere = PrivateSphereCovert.toPrivateSphere(privateSphereDTO);
        privateSphere = checkPrivateSphere(privateSphere);

        if (stopCustomerLoseConsumeOn) {
            if (checkIsStopConsumeStatus(privateSphere.getCorpId())) {
                log.info("该corpId还未完成切流, 客户流失消息暂停发送, 新云在消费, corpId:{}", privateSphere.getCorpId());
                return true;
            }
        }

        try {
            log.info("C端发送客户流失消息, request:{}", JSON.toJSONString(customerLoseNoticeDTO));
            Integer type = customerLoseNoticeDTO.getType();
            if (Objects.nonNull(type) && type == 1) {
                sendCLoseMessage(privateSphere, customerLoseNoticeDTO.getUserId(), customerLoseNoticeDTO.getExternalUserName(), customerLoseNoticeDTO.getExternalUserId());
            }
        } catch (Exception e) {
            log.error("C端发送客户流失消息失败, request:{}, error:", JSON.toJSONString(customerLoseNoticeDTO), e);
        }

        return true;
    }

    @Override
    public Boolean employeeDeleteCustomerWarnNotice(EmployeeDeleteCustomerMsgDTO employeeDeleteCustomerMsgDTO) {
        log.info("员工删除客户警告, 消息推送, request:{}", JSON.toJSONString(employeeDeleteCustomerMsgDTO));
        PrivateSphere privateSphere = employeeDeleteCustomerMsgDTO.getPrivateSphere();
        List<PrivateSphereVid> vids = privateSphere.getVids();
        if (CollectionUtils.isEmpty(vids)) {
            log.warn("发送流失提醒失败, vids查询为空, privateSphere:{}", JSON.toJSONString(privateSphere));
            return false;
        }

        try {
            MultiResponse<Employee> employeeMultiResponse = employeeProxy.getByEmployeeIdOrTxUserIds(privateSphere, employeeDeleteCustomerMsgDTO.getNoticeEmployeeIds(), null);
            if (employeeMultiResponse != null && CollectionUtils.isNotEmpty(employeeMultiResponse.getDataList())) {
                for (Employee employeeEntity : employeeMultiResponse.getDataList()) {
                    EmployeeStatusEnum status = employeeEntity.getStatus();
                    EmployeeActiveStatusEnum activeStatus = employeeEntity.getActiveStatus();
                    if (EmployeeActiveStatusEnum.INACTIVE.equals(activeStatus) || EmployeeStatusEnum.USER_UN_AUTHORIZATION.equals(status)) {
                        log.warn("员工删除客户警告, 消息推送, 员工状态异常, status:{},activeStatus:{}", status, activeStatus);
                        continue;
                    }
                    sendCLoseMessage1(privateSphere, employeeEntity.getTxUserId(), employeeDeleteCustomerMsgDTO.getDeleteEmployeeName(),
                            employeeDeleteCustomerMsgDTO.getDeleteNum());
                }
            }

        } catch (Exception e) {
            log.error("C端发送客户流失消息失败, privateSphere:{}, request:{}, error:{}",
                    JSON.toJSONString(privateSphere), JSON.toJSONString(employeeDeleteCustomerMsgDTO), e);
        }


        return true;
    }

    @Override
    public Boolean customerRemindNotice(CustomerRemindMsgDTO customerRemindMsgDTO) {
        log.info("客户跟进提醒，消息开始推送，参数：{}", JsonUtil.obj2Str(customerRemindMsgDTO));

        ClueCfg clueCfg = customerRemindMsgDTO.getClueCfg();
        PrivateSphere privateSphere = customerRemindMsgDTO.getPrivateSphere();
        String txUserId = customerRemindMsgDTO.getTxUserId();
        String stageName = customerRemindMsgDTO.getStageName();

        String tcode = privateSphere.getTcode();
        String url = stageJumpUrlMap.get(tcode);
        if (StringUtils.isBlank(url)) {
            log.error("customerRemindNotice.privateSphere.tcode is :{},cfg:{}", tcode, JSON.toJSON(stageJumpUrlMap));
            return Boolean.FALSE;
        }
        //msg消息体构建
        String sid = newRemoteOutServiceProxy.fetchSid(privateSphere, StypeEnum.CUSTOMER_STAGE_DETAIL.getType());
        String jumpUrl = String.format(url, sid, customerRemindMsgDTO.getStageId());
        String mainMsg = String.format(customerFollowRemind, stageName, clueCfg.getRuleExtendInfo(), jumpUrl);
        if (StringUtil.isEmpty(sid)) {
            log.error("customerRemindNotice sid is null");
            return Boolean.FALSE;
        }
        log.info("customerRemindNotice sid:{}", sid);
        sendCorpAgentMessage(privateSphere, mainMsg, txUserId);
        return Boolean.TRUE;
    }


    private PrivateSphere checkPrivateSphere(PrivateSphere privateSphere) {
        if (Objects.isNull(privateSphere)) {
            throw new BizException("私域信息不能为空");
        }

        if (Objects.nonNull(privateSphere.getBosId())
                && StringUtils.isNotBlank(privateSphere.getCorpId())
                && StringUtils.isNotBlank(privateSphere.getPrivateSphereId())
                && Objects.nonNull(privateSphere.getProductInstanceId())
                && StringUtils.isNotBlank(privateSphere.getAgentId())) {
            return privateSphere;
        }

        return privateSphereThird.fetch(privateSphere.getCorpId(),
                privateSphere.getBosId(), privateSphere.getPrivateSphereId(), privateSphere.getProductInstanceId());
    }


    private void sendCLoseMessage(PrivateSphere privateSphere, String txUserIds, String externalUserName, String externalUserId) {
        if (StringUtils.isBlank(privateSphere.getAgentId()) && StringUtils.isBlank(privateSphere.getProxiedAgentId())) {
            throw new BizException("agentId 不能为空");
        }

        String url = this.getCustomerChatDetailUrl(privateSphere.getProductInstanceId(), privateSphere.getTcode(), externalUserId);
        String content = String.format(externalUserDelUser, externalUserName, url);
        sendCorpAgentMessage(privateSphere, content, txUserIds);
    }

    /**
     * 客户聊天框
     * 获取跳转详情URL
     */
    private String getCustomerChatDetailUrl(Long productInstanceId, String tCode, String externalUserId) {
        SidInfo sidInfo = fetchSid(productInstanceId, tCode, StypeEnum.CUSTOMER_CHAT.getType());
        String sid = sidInfo.getSid();
        String url = null;
        if (StringUtils.isNotBlank(sidInfo.getUrl())) {
            url = sidInfo.getUrl() + jumpCustomerParams;
        }
        return String.format(url, sid, externalUserId, BATCH_CUSTOMER);
    }

    /**
     * 获取sid
     *
     * @param productInstanceId productInstanceId
     * @param sidebarType       sidebarType
     * @return String String
     */
    public SidInfo fetchSid(Long productInstanceId, String tCode, Integer sidebarType) {
        if (productInstanceId == null || sidebarType == null) {
            throw new BizException("productInstanceId或者sidebarType为空");
        }
        // 1.构造请求参数
        SingleSidInfoRequest request = new SingleSidInfoRequest();
        request.setPiid(productInstanceId);
        request.setStype(sidebarType);
        request.setTcode(tCode);

        // 2.执行请求
        SidInfo sidInfo = SoaUtil.unpack(sidInfoService.fetch(request));
        if (sidInfo == null || StringUtils.isBlank(sidInfo.getSid())) {
            log.error("productInstanceId:{},sid:{}", productInstanceId, sidebarType);
            throw new BizException("未查询到此productInstanceId和type对应的sid");
        }
        return sidInfo;
    }

    private void sendCLoseMessage1(PrivateSphere privateSphere, String txUserIds, String employeeName, Integer deleteNum) {
        if (StringUtils.isBlank(privateSphere.getAgentId()) && StringUtils.isBlank(privateSphere.getProxiedAgentId())) {
            throw new BizException("agentId 不能为空");
        }

        //CorpAgentReqDTO<SendMessageReqDTO> corpAgentReqDTO = new CorpAgentReqDTO<>();


        SendDkOrSelfAgentMessageDTO sendDkOrSelfAgentMessageDTO = new SendDkOrSelfAgentMessageDTO();
        //AgentAuthInfoDTO agentAuthInfo = new AgentAuthInfoDTO();
        sendDkOrSelfAgentMessageDTO.setCorpId(privateSphere.getCorpId());
        //agentAuthInfo.setAgentId(privateSphere.getAgentId());
        //corpAgentReqDTO.setAuth(agentAuthInfo);

        //SendMessageReqDTO sendMessageReqDTO = new SendMessageReqDTO();
        if (StringUtils.isNotBlank(privateSphere.getAgentId())) {
            sendDkOrSelfAgentMessageDTO.setAgentid(Long.valueOf(privateSphere.getAgentId()));
        }

        if (StringUtils.isNotBlank(privateSphere.getProxiedAgentId())) {
            sendDkOrSelfAgentMessageDTO.setAgentid(Long.parseLong(privateSphere.getProxiedAgentId()));
        }

        sendDkOrSelfAgentMessageDTO.setTemplateId(privateSphere.getTemplateId());

        sendDkOrSelfAgentMessageDTO.setMsgtype("text");
        sendDkOrSelfAgentMessageDTO.setTouser(txUserIds);


        SendMessageReqDTO.TextContent textContent = new SendMessageReqDTO.TextContent();
        textContent.setContent(String.format(customerDelEmployeeWarn, employeeName, deleteNum));

        sendDkOrSelfAgentMessageDTO.setText(textContent);


        //corpAgentReqDTO.setRequest(sendMessageReqDTO);

        log.info("调用adapter发送C端消息, request:{}", JSON.toJSONString(sendDkOrSelfAgentMessageDTO));
        SoaResponse<SendMessageRespDTO, Void> sendMessageRespDTOVoidSoaResponse =
                channelAdapterService.sendDkOrSelfAgentMessage(sendDkOrSelfAgentMessageDTO);
        log.info("调用adapter发送C端消息返回结果, request:{}, response:{}", JSON.toJSONString(sendDkOrSelfAgentMessageDTO),
                JSON.toJSONString(sendMessageRespDTOVoidSoaResponse));
    }


    private Boolean checkIsStopConsumeStatus(String corpId) {

        Set<Long> bosIds = bosThird.getBosIdListByCorpId(corpId);
        if (CollectionUtils.isEmpty(bosIds)) {
            return false;
        }
        log.info("切流判断, 根据corpId查询pid, corpId:{}, pidList:{}", corpId, JSON.toJSONString(bosIds));

        BatchMigrationStatusRequest request = new BatchMigrationStatusRequest();
        request.setBosId(Lists.newArrayList(bosIds));
        log.info("查询bosIdList迁移状态, request:{}", JSON.toJSONString(request));
        SoaResponse<List<BatchMigrationStatusVo>, Void> listVoidSoaResponse = ecAdapterService.batchMigrationStatus(request);
        log.info("查询bosIdList迁移状态响应结果, request:{}, response:{}", JSON.toJSONString(request), JSON.toJSONString(listVoidSoaResponse));
        List<BatchMigrationStatusVo> unpack = SoaUtil.unpack(listVoidSoaResponse);
        if (org.springframework.util.CollectionUtils.isEmpty(unpack)) {
            return true;
        }

        for (BatchMigrationStatusVo batchMigrationStatusVo : unpack) {
            Integer status = batchMigrationStatusVo.getStatus();
            if (Objects.nonNull(status)) {
                if (1 == status || 3 == status) {
                    return true;
                }
            }
        }

        return false;
    }


    /**
     * 发送消息  自建应用 or 代自建
     *
     * @param privateSphere privateSphere
     * @param msg           msg
     * @param toUser        txUserId
     * @return Boolean
     */
    public Boolean sendCorpAgentMessage(PrivateSphere privateSphere, String msg, String toUser) {
        SendDkOrSelfAgentMessageDTO request = new SendDkOrSelfAgentMessageDTO();
        request.setCorpId(privateSphere.getCorpId());
        request.setTemplateId(privateSphere.getTemplateId());
        String proxiedAgentId = privateSphere.getProxiedAgentId();

        if (!StringUtils.isEmpty(proxiedAgentId)) {
            request.setAgentid(Long.parseLong(proxiedAgentId));
        }
        request.setMsgtype("text");

        SendMessageReqDTO.TextContent textContent = new SendMessageReqDTO.TextContent();
        textContent.setContent(msg);
        request.setText(textContent);
        request.setTouser(toUser);

        SoaResponse<SendMessageRespDTO, Void> soaResponse = null;
        try {
            log.info("MsgNoticeServiceImpl#sendMessage入参:{}", JSON.toJSONString(request));
            soaResponse = channelAdapterService.sendDkOrSelfAgentMessage(request);
            log.info("MsgNoticeServiceImpl#sendMessage结果:{}", JSON.toJSONString(soaResponse));
        } catch (Exception e) {
            log.error("channelAdapterService.sendMessage error ", e);
            throw new BizException(e.getMessage());
        }

        Assert.notNull(soaResponse, "soaResponse must not null");
        if (!SoaUtil.isSucc(soaResponse) && !codeList.contains(soaResponse.getReturnCode())) {
            log.error("channelAdapterService.sendMessage，发送失败：{}", JSON.toJSONString(soaResponse));
            throw new BizException(soaResponse.getReturnMsg());
        }

        return Boolean.TRUE;
    }
}
